import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.sql.*;
import java.time.LocalDateTime;

public class Main {

    private static String flagTable = "ddl_finish_flag";

    public static void main(String[] args) throws IOException, InterruptedException, SQLException {
        // 获取配置
        if (!Property.init(args)) {
            return;
        }

        Log.init();
        DataGen.init();
        
        if (Property.runMode.equals("build")) {
            build();
        } else if (Property.runMode.equals("run")) {
            run();
        } else {
            System.out.println("ERROR");
        }
    }
    
    public static void build() throws IOException, SQLException, InterruptedException {
        if (checkHasBuilt()) {
            Log.info("检测到已存在数据库对象，跳过创建.");
        } else {
            Log.info("未检测到数据库对象，进行创建.");
            Connection conn = DriverManager.getConnection(Property.primaryDbURL, Property.username, Property.password);
            Statement stmt = conn.createStatement();
            String currentPath = Main.class.getProtectionDomain().getCodeSource().getLocation().getPath();
            String file = currentPath + "/ddl/" + Property.ddl + ".sql";
            
            Log.info("=================== Executing file:" + file + "===================");
            StringBuilder sql = new StringBuilder();
            BufferedReader br = new BufferedReader(new FileReader(file));
            String line;
            while ((line = br.readLine()) != null) {
                sql.append(line);
                sql.append(System.lineSeparator());
            }
            String[] sqlCommands = sql.toString().split(";");
            stmt.execute("set search_path = public;");
            for(String sqlCommand: sqlCommands) {
                if (!sqlCommand.trim().isEmpty()) {
                    Log.info("execute SQL:\n" + sqlCommand);
                    stmt.execute(sqlCommand);
                }
            }
            
            Log.info("创建build标志表" + flagTable);
            stmt.execute("create table " + flagTable + " (key text, value text);");
            stmt.close();
            conn.close();
            Log.info("数据库对象创建完成.");
        }
        
        if (!ProduceSystem.init()) {
            ProduceSystem.shutdown();
            Log.err("启动失败。");
            return;
        }
        ProduceSystem.run();

        String statisticRes = "";
        long endTime = System.currentTimeMillis() + 1000 * 60 * Property.runMins;
        while (Property.runMins <= 0 || System.currentTimeMillis() < endTime) {
            statisticRes = ProduceSystem.statistic();
            Thread.sleep(1000);
        }
        ProduceSystem.shutdown();

        Log.info("FINAL RES: " + statisticRes);
        Log.info("导入结束。");
        
    }
    
    public static void run() throws IOException, SQLException, InterruptedException {
        if (!checkHasBuilt()) {
            Log.err("请先build来建立数据库对象与导入基础数据。");
            return;
        }
        
        if (!ProduceSystem.init() || !ConsumeSystem.init() || !CleanSystem.init()) {
            ProduceSystem.shutdown();
            ConsumeSystem.shutdown();
            CleanSystem.shutdown();
            Log.err("启动失败.");
            return;
        }
        ProduceSystem.run();
        ConsumeSystem.run();
        CleanSystem.run();
        
        String statisticRes1 = "";
        String statisticRes2 = "";
        long endTime = System.currentTimeMillis() + 1000 * 60 * Property.runMins;
        while (Property.runMins <= 0 || System.currentTimeMillis() < endTime) {
            statisticRes1 = ProduceSystem.statistic();
            statisticRes2 = ConsumeSystem.statistic();
            Thread.sleep(1000);
        }
        ConsumeSystem.shutdown();
        ProduceSystem.shutdown();
        CleanSystem.shutdown();
        
        Log.info("FINAL RES: " + statisticRes1);
        Log.info("FINAL RES: " + statisticRes2);
        Log.info("测试结束.");
    }
    
    private static boolean checkHasBuilt() throws SQLException {
        Connection conn = DriverManager.getConnection(Property.primaryDbURL, Property.username, Property.password);
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery("select count(*) from pg_class where relname = '" + flagTable + "'");
        rs.next();
        int count = rs.getInt(1);
        stmt.close();
        conn.close();
        return count == 1;
    }
}

